/*
 * @(#)AssVertexViewComponent.java   09/12/30
 * 
 * Copyright (C) 2009 Ecole des Mines d'Ales
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Contact: yulinz88@gmail.com
 */



package fr.ema.arch3d.editor.ass;

import org.jgraph.graph.CellViewRenderer;
import org.jgraph.graph.EdgeView;
import org.jgraph.graph.GraphConstants;
import org.jgraph.graph.VertexRenderer;
import org.jgraph.graph.VertexView;

import java.awt.BasicStroke;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

//~--- classes ----------------------------------------------------------------

/**
 * @author Zhang yulin(huaxi)
 *
 */
public class AssVertexViewComponent extends VertexView {

    /**
     */
    public static transient MyVertexViewRenderer renderer = new MyVertexViewRenderer();

    /**
     */
    public AssVertexViewComponent() {
        super();
    }

    /**
     *
     * @param cell
     */
    public AssVertexViewComponent(Object cell) {
        super(cell);
    }

    /**
     * Returns the intersection of the bounding rectangle and the
     * straight line between the source and the specified point p.
     * The specified point itfP expected not to intersect the bounds.
     * @param edge  
     * @param source  
     * @param p  
     * @return  
     */
    public Point2D getPerimeterPoint(EdgeView edge, Point2D source, Point2D p) {
        Rectangle2D r = getBounds();
        double      x = r.getX();
        double      y = r.getY();
        double      a = (r.getWidth() + 1) / 2;
        double      b = (r.getHeight() + 1) / 2;

        // x0,y0 - center of ellipse
        double x0 = x + a;
        double y0 = y + b;

        // x1, y1 - point
        double x1 = p.getX();
        double y1 = p.getY();

        // calculate straight line equation through point and ellipse center
        // y = d * x + h
        double dx = x1 - x0;
        double dy = y1 - y0;

        if (dx == 0) {
            return new Point((int) x0, (int) (y0 + b * dy / Math.abs(dy)));
        }

        double d = dy / dx;
        double h = y0 - d * x0;

        // calculate intersection
        double e   = a * a * d * d + b * b;
        double f   = -2 * x0 * e;
        double g   = a * a * d * d * x0 * x0 + b * b * x0 * x0 - a * a * b * b;
        double det = Math.sqrt(f * f - 4 * e * g);

        // two solutions (perimeter points)
        double xout1        = (-f + det) / (2 * e);
        double xout2        = (-f - det) / (2 * e);
        double yout1        = d * xout1 + h;
        double yout2        = d * xout2 + h;
        double dist1Squared = Math.pow((xout1 - x1), 2) + Math.pow((yout1 - y1), 2);
        double dist2Squared = Math.pow((xout2 - x1), 2) + Math.pow((yout2 - y1), 2);

        // correct solution
        double xout, yout;

        if (dist1Squared < dist2Squared) {
            xout = xout1;
            yout = yout1;
        } else {
            xout = xout2;
            yout = yout2;
        }

        return getAttributes().createPoint(xout, yout);
    }

    /**
     * @return  
     */
    public CellViewRenderer getRenderer() {
        return renderer;
    }

    /**
     */
    public static class MyVertexViewRenderer extends VertexRenderer {

        /**
         * Return a slightly larger preferred size than for a rectangle.
         * @return  
         */
        public Dimension getPreferredSize() {
            Dimension d = super.getPreferredSize();

            d.width  += d.width / 8;
            d.height += d.height / 2;

            return d;
        }

        /**
         * @param g  
         */
        public void paint(Graphics g) {
            int        b   = borderWidth;
            Graphics2D g2  = (Graphics2D) g;
            Dimension  d   = getSize();
            boolean    tmp = selected;

            if (super.isOpaque()) {
                g.setColor(super.getBackground());

                if ((gradientColor != null) &&!preview) {
                    setOpaque(false);
                    g2.setPaint(new GradientPaint(0, 0, getBackground(), getWidth(), getHeight(), gradientColor, true));
                }

                // g.fillOval(b - 1, b - 1, d.width - b, d.height - b);
                g.fillRect(b - 1, b - 1, d.width - b, d.height - b);
            }

            try {
                setBorder(null);
                setOpaque(false);
                selected = false;
                super.paint(g);
            } finally {
                selected = tmp;
            }

            if (bordercolor != null) {
                g.setColor(bordercolor);
                g2.setStroke(new BasicStroke(b));
                g.drawRect(b - 1, b - 1, d.width - b, d.height - b);
                g.drawRect(b + 4, b + 4, d.width - b - 10, d.height - b - 10);
            }

            if (selected) {
                g2.setStroke(GraphConstants.SELECTION_STROKE);
                g.setColor(highlightColor);
                g.drawRect(b - 1, b - 1, d.width - b, d.height - b);
            }
        }
    }
}
